package demo;

import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyShell;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.junit.Test;

import java.io.File;
import java.io.IOException;

public class Demo2 {

    /**
     * 利用一个常用基类执行脚本<p>
     * 将Groovy脚本继承自一个你选择的基类，之后便可以访问脚本的常规方法，这种做法往往非常有用。
     * 可以通过在编译配置中设置脚本基类属性，并将新的编译配置传递给shell完成这一操作。
     */
    @Test
    public void test1() {
        CompilerConfiguration configuration = new CompilerConfiguration();
        configuration.setScriptBaseClass("demo.ScriptBaseTestScript");
        ClassLoader classLoader = configuration.getClass().getClassLoader();
        GroovyShell shell = new GroovyShell(classLoader, new Binding(), configuration);
        Object result = shell.evaluate("foo()");
        // 执行结果
        System.out.printf("执行结果：%s, 类型: %s\n", result, result.getClass().getCanonicalName());
    }

    /**
     * 在Java中动态加载和运行Groovy脚本
     * <p>
     * 你可以在Java代码中直接使用GroovyClassLoader动态地加载和执行Groovy类。
     *
     * @throws IOException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Test
    public void test2() throws IOException, IllegalAccessException, InstantiationException {
        ClassLoader parent = getClass().getClassLoader();

        GroovyClassLoader loader = new GroovyClassLoader(parent);

        Class groovyClass = loader.parseClass(new File("src/main/groovy/demo/HelloWorld.groovy"));

        // let's call some method on an instance
        GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();

        Object[] args = {};

        groovyObject.invokeMethod("run", args);
    }

    /**
     * 在Java里使用一个接口，但是接口的实现在Groovy脚本中
     *
     * @throws IOException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    @Test
    public void test3() throws IOException, IllegalAccessException, InstantiationException {
        String fileName = "src/main/groovy/demo/Tester.groovy";

        GroovyClassLoader gcl = new GroovyClassLoader();

        Class clazz = gcl.parseClass(new File(fileName));

        Object aScript = clazz.newInstance();

        TestInterface ifc = (TestInterface) aScript;

        ifc.printIt();
    }

}
